﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using DotNetDal.Core;
using DotNetDal.Core.Model;
using DotNetDalAddin.Properties;
using System.IO;
using EnvDTE;

namespace DotNetDalAddin
{
    public partial class Generator : Form
    {
        #region Private Fields
        private TreeNode rightClickedTreeNode;
        private EnvDTE80.DTE2 HostApplication;
        #endregion

        public Generator(EnvDTE80.DTE2 application)
        {
            HostApplication = application;

            InitializeComponent();

            try
            {
                loadProjectList();

                while (Properties.Settings.Default.SqlConnection == "")
                {
                    SetSqlConnectionString();

                    if (Properties.Settings.Default.SqlConnection == "")
                        MessageBox.Show("Please choose a valid connection");
                }

                DotNetDal.Core.SqlServer.RegisterSqlConnectionString(Settings.Default.SqlConnection);

                RefreshTree();
            }
            catch (System.Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        public void SetSqlConnectionString()
        {
            Microsoft.Data.ConnectionUI.DataConnectionDialog dcd = new Microsoft.Data.ConnectionUI.DataConnectionDialog();

            if (Properties.Settings.Default.SqlConnection != "")
                dcd.ConnectionString = Properties.Settings.Default.SqlConnection;

            dcd.DataSources.Add(Microsoft.Data.ConnectionUI.DataSource.SqlDataSource);

            Microsoft.Data.ConnectionUI.DataConnectionDialog.Show(dcd);

            Settings.Default.SqlConnection = dcd.ConnectionString;
            Settings.Default.Save();
        }

        public void RefreshTree()
        {
            tvDatabase.Nodes.Clear();

            Database db = Database.RetrieveDatabase();

            TreeNode rootNode = new TreeNode(db.Name);
            rootNode.ImageKey = rootNode.SelectedImageKey = "Database.png";
            rootNode.Tag = db;
            rootNode.ContextMenuStrip = cmsEntity;

            tvDatabase.Nodes.Add(rootNode);

            foreach (Schema s in db.Schemas)
            {
                TreeNode sNode = new TreeNode(Text = s.Name);
                sNode.ImageKey = sNode.SelectedImageKey = "Schema.png";
                sNode.Tag = s;
                sNode.ContextMenuStrip = cmsEntity;

                rootNode.Nodes.Add(sNode);

                foreach (Table t in s.Tables)
                {
                    TreeNode tNode = new TreeNode(Text = t.Name);
                    tNode.ImageKey = tNode.SelectedImageKey = "Table.png";
                    tNode.Tag = t;
                    tNode.ContextMenuStrip = cmsEntity;

                    sNode.Nodes.Add(tNode);

                    foreach (Field f in t.Fields)
                    {
                        TreeNode fNode = new TreeNode(Text = f.Name);
                        fNode.ImageKey = fNode.SelectedImageKey = "Field.png";
                        fNode.Tag = f;

                        tNode.Nodes.Add(fNode);
                    }
                }
            }

            tvDatabase.Nodes[0].Expand();
            this.Text = "DotNetDal Addin";
        }

        private void loadProjectList()
        {
            Settings.Default.ProjectList = new System.Collections.Specialized.StringCollection();

            List<string> projList = new List<string>();

            foreach (EnvDTE.Project p in this.HostApplication.Solution.Projects)
                projList.Add(p.Name);

            projList.Sort();

            cbProjectList.Items.AddRange(projList.ToArray());

            cbProjectList.SelectedIndex = cbProjectList.FindString(Settings.Default.SelectedProject);

        }

        private void tvDatabase_AfterSelect(object sender, TreeViewEventArgs e)
        {
            propertyGrid1.SelectedObject = e.Node.Tag;
        }
        private void tvDatabase_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e)
        {
            if (e.Button == MouseButtons.Right && e.Node != null)
            {
                rightClickedTreeNode = e.Node;
            }
        }
        private void generateCodeToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Database d = rightClickedTreeNode.Tag as Database;
            Schema s = rightClickedTreeNode.Tag as Schema;
            Table t = rightClickedTreeNode.Tag as Table;

            if (d != null)
            {
                foreach (TreeNode node in rightClickedTreeNode.Nodes)
                {
                    foreach (TreeNode childNode in node.Nodes)
                    {
                        generateEntity(childNode.Tag as Table);
                    }
                }
            }
            else if (s != null)
            {
                foreach (TreeNode node in rightClickedTreeNode.Nodes)
                {
                    generateEntity(node.Tag as Table);
                }
            }
            else if (t != null)
            {
                generateEntity(rightClickedTreeNode.Tag as Table);
            }


        }

        private void generateEntity(Table t)
        {
            EnvDTE.Project project = null;
            foreach (EnvDTE.Project p in this.HostApplication.Solution.Projects)
                if (p.Name == cbProjectList.SelectedItem.ToString())
                    project = p;

            string projectFolder = project.Properties.Item("FullPath").Value.ToString();

            /*
                Add/Get Data Directory 
            */
            string dataFolder = System.IO.Path.Combine(projectFolder, "AbstractEntities");
            if (!System.IO.Directory.Exists(dataFolder)) System.IO.Directory.CreateDirectory(dataFolder);

            EnvDTE.ProjectItem dataPi = null;
            foreach (EnvDTE.ProjectItem item in project.ProjectItems)
                if (item.Name == Settings.Default.AbstractFolderName)
                    dataPi = item;

            if (dataPi == null)
                dataPi = project.ProjectItems.AddFromDirectory(dataFolder);

            string dataCode = new CodeHelper.DataCodeTable(t).GenerateCode(cbProjectList.SelectedItem.ToString());
            addDataClass(dataPi, t.Name, dataFolder, dataCode);

            /*
                Add/Get Business Directory 
            */
            string busFolder = System.IO.Path.Combine(projectFolder, "Entities");
            if (!System.IO.Directory.Exists(busFolder)) System.IO.Directory.CreateDirectory(busFolder);

            EnvDTE.ProjectItem businessPi = null;
            foreach (EnvDTE.ProjectItem item in project.ProjectItems)
                if (item.Name == Settings.Default.BusinessFolderName)
                    businessPi = item;

            if (businessPi == null)
                businessPi = project.ProjectItems.AddFromDirectory(busFolder);

            bool businessClassFileExists = false;
            foreach (ProjectItem file in businessPi.ProjectItems)
                if (file.Name == (t.Name + ".cs"))
                    businessClassFileExists = true;

            if (!businessClassFileExists)
            {
                string busCode = new CodeHelper.BusinessCodeTable(t).GenerateCode(cbProjectList.SelectedItem.ToString());
                addBusinessClass(businessPi, t.Name, busFolder, busCode);
            }
        }
        private void addDataClass(ProjectItem dataPi, string name, string dataFolder, string code)
        {
            string fileName = Path.Combine(dataFolder, "Abstract" + name + ".cs");
            StreamWriter sw = File.CreateText(fileName);
            sw.Write(code);
            sw.Close();

            ProjectItem dataclasspi = dataPi.ProjectItems.AddFromFile(fileName);

            Window w = dataclasspi.Open(Constants.vsViewKindCode);
            w.Activate();
            TextSelection ts = (TextSelection)w.Selection;
            ts.SelectAll();
            ts.SmartFormat();
        }
        private void addBusinessClass(ProjectItem busPi, string name, string busFolder, string code)
        {
            string fileName = Path.Combine(busFolder, name + ".cs");
            StreamWriter sw = File.CreateText(fileName);
            sw.Write(code);
            sw.Close();

            ProjectItem busClassPi = busPi.ProjectItems.AddFromFile(fileName);

            Window w = busClassPi.Open(Constants.vsViewKindCode);
            w.Activate();
            TextSelection ts = (TextSelection)w.Selection;
            ts.SelectAll();
            ts.SmartFormat();
        }

        private void cbProjectList_SelectedIndexChanged(object sender, EventArgs e)
        {
            Settings.Default.SelectedProject = cbProjectList.SelectedItem.ToString();
            Settings.Default.Save();
        }

        private void btConfigure_Click(object sender, EventArgs e)
        {
            Configure frm = new Configure(this);
            frm.ShowDialog();
        }
    }
}
